package com.wh.connection_pool;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

public class ConnectionPoolImpl implements ConnectionPool {

	private DBbean dBbean;
	private boolean isActive = false;	//连接活动状态
	private int contActive = 0; //记录创建的总连接数
	
	//空闲连接
	private List<Connection> freeConnection = new Vector<Connection>();
	//活动连接
	private List<Connection> activeConnection = new Vector<Connection>();
	
	private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
	
	public ConnectionPoolImpl(DBbean dBbean) {
		this.dBbean = dBbean;
		init();
		
	}
	
	
	public void init() {
		try {
			Class.forName(dBbean.getDriverName());
			for(int i = 0; i < dBbean.getInitConnnections(); i++) {
				Connection connection = newConnection();
				if(connection != null) {
					freeConnection.add(connection);
					contActive ++;
				}
			}
			isActive = true;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	public Connection newConnection() throws ClassNotFoundException, SQLException {
		Connection connection = null;
		if(dBbean != null ) {
			Class.forName(dBbean.getDriverName());
			connection = DriverManager.getConnection(dBbean.getUrl(), dBbean.getUsername(), dBbean.getPassword());
		}
		return connection;
	}
	
	@Override// 获得连接  
	public synchronized Connection getConnection() {
		Connection connection = null;
		try {
			// 判断是否超过最大连接数限制  
			if(contActive < this.dBbean.getMaxActiveConnections()) {
				if(freeConnection.size() > 0) {
					connection = freeConnection.get(0);
					if(connection != null) {
						threadLocal.set(connection);
					}
					freeConnection.remove(0);
				} else {
					connection = newConnection();
				}
			} else {
				// 继续获得连接,直到从新获得连接  
				this.wait(dBbean.getConnTimeout());
				connection = getConnection();
			}
			if(isValid(connection)) {
				freeConnection.remove(connection);
				activeConnection.add(connection);
				contActive ++;
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public Connection getCurrentConnection() {
		Connection connection = threadLocal.get();
		if(!isValid(connection)) {
			connection = this.getConnection();
		}
		return connection;
	}

	//释放连接
	@Override
	public synchronized void releaseConn(Connection connection) throws SQLException {
		if(isValid(connection) && (freeConnection.size() < dBbean.getMaxConnections())) {
			freeConnection.add(connection);
			activeConnection.remove(connection);
			contActive --;
			threadLocal.remove();
			// 唤醒所有正待等待的线程，去抢连接  
			this.notifyAll();
		}
	}
	
	@Override
	public void destory() {
		for(Connection connection : freeConnection) {
			if(!isValid(connection)) {
				try {
					connection.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		for(Connection connection : activeConnection) {
			if(!isValid(connection)) {
				try {
					connection.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		isActive = false;
		contActive = 0;
	}

	@Override
	public boolean isActive() {
		// TODO Auto-generated method stub
		return this.isActive;
	}

	@Override
	public void checkPool() {
		if(this.dBbean.isCheckPool()) {
			new Timer().schedule(new TimerTask() {
				
				@Override
				public void run() {
					// TODO Auto-generated method stub
					System.out.println("空闲连接池的个数" + freeConnection.size());
					System.out.println("活动连接数" + activeConnection.size());
					System.out.println("总的连接数" + contActive);
				}
			}, this.dBbean.getLazyCheckTime(), this.dBbean.getPeriodCheck());
		}
		
	}
	
	private boolean isValid(Connection conn) {
		
		try {
			if(conn == null || conn.isClosed()) {
				return false;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return true;
	}

}
